package com.lonewalker.snail.controller.flow;

import com.lonewalker.snail.common.base.ApiResult;
import com.lonewalker.snail.domain.entity.SysUser;
import com.lonewalker.snail.domain.request.*;
import com.lonewalker.snail.domain.vo.TaskVo;
import com.lonewalker.snail.service.ProcessInstanceService;
import com.lonewalker.snail.service.ProcessTaskService;
import com.lonewalker.snail.util.UserUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 流程实例相关接口
 *
 * @author lonewalker
 */
@RequestMapping("/process/instance")
@RequiredArgsConstructor
@RestController
public class ProcessInstanceController {

    private final ProcessInstanceService processInstanceService;
    private final ProcessTaskService processTaskService;

    /**
     * 根据流程定义key发起流程实例
     *
     * @param requestParam 请求参数
     * @return 流程实例id
     */
    @PostMapping("/startProcessInstanceByKey")
    public ApiResult<String> startProcessInstanceByKey(@RequestBody StartProcessRequest requestParam) {
        SysUser userInfo = UserUtil.getUserInfo();
        return processInstanceService.startProcessInstanceByKey(userInfo, requestParam);
    }

    /**
     * 根据流程定义id发起流程实例
     *
     * @param requestParam 请求参数
     * @return 流程实例id
     */
    @PostMapping("/startProcessInstanceById")
    public ApiResult<String> startProcessInstanceById(@RequestBody StartProcessRequest requestParam) {
        SysUser userInfo = UserUtil.getUserInfo();
        return processInstanceService.startProcessInstanceById(userInfo, requestParam);
    }

    /**
     * 查询当前用户的待办任务--针对单个业务
     *
     * @param businessKey 业务key
     * @param userId      用户id
     * @return 待办任务信息
     */
    @GetMapping("/listToDoTaskBySingle")
    public ApiResult<List<TaskVo>> listToDoTaskBySingle(@RequestParam("businessKey") String businessKey,
                                                        @RequestParam("userId") Long userId) {
        //正常情况下直接获取当前登录人信息即可，这里模拟一下吧
        SysUser userInfo = UserUtil.getUserInfo();
        userInfo.setId(userId);
        return processTaskService.listToDoTaskBySingle(userInfo, businessKey);
    }

    /**
     * 查询当前用户的待办任务--针对多个业务
     *
     * @param businessKeys 业务key
     * @param userId       用户id
     * @return 待办任务信息
     */
    @GetMapping("/listToDoTaskByMulti")
    public ApiResult<List<TaskVo>> listToDoTaskByMulti(@RequestParam("businessKeys") String[] businessKeys,
                                                       @RequestParam("userId") Long userId) {
        SysUser userInfo = UserUtil.getUserInfo();
        userInfo.setId(userId);
        return processTaskService.listToDoTaskByMulti(userInfo, businessKeys);
    }

    /**
     * 分页查询用户指定业务的待办任务
     *
     * @param businessKey 业务key
     * @param userId      用户id
     * @param pageNum     页码
     * @param pageSize    数量
     * @return 待办任务信息
     */
    @GetMapping("/pageToDoTask")
    public ApiResult<List<TaskVo>> pageToDoTask(@RequestParam("businessKey") String businessKey,
                                                @RequestParam("userId") Long userId,
                                                @RequestParam("pageNum") Integer pageNum,
                                                @RequestParam("pageSize") Integer pageSize) {
        //正常情况下直接获取当前登录人信息即可，这里模拟一下吧
        SysUser userInfo = UserUtil.getUserInfo();
        userInfo.setId(userId);
        return processTaskService.pageToDoTask(userInfo, businessKey, pageNum, pageSize);
    }


    /**
     * 完成单个任务
     *
     * @param requestParam 请求参数
     * @return 任务所在节点信息
     */
    @PostMapping("/completeSingleTask")
    public ApiResult<Map<String, String>> completeSingleTask(@RequestBody @Validated CompleteTaskRequest requestParam) {
        return processTaskService.completeSingleTask(requestParam);
    }

    /**
     * 转办任务
     *
     * @param requestParam 请求参数
     */
    @PostMapping("/transferTask")
    public ApiResult<Void> transferTask(@RequestBody @Validated TransferTaskRequest requestParam) {
        return processTaskService.transferTask(requestParam);
    }

    /**
     * 委托任务
     *
     * @param requestParam 请求参数
     */
    @PostMapping("/delegateTask")
    public ApiResult<Void> delegateTask(@RequestBody @Validated DelegateTaskRequest requestParam) {
        return processTaskService.delegateTask(requestParam);
    }

    /**
     * 解决任务
     *
     * @param requestParam 请求参数
     */
    @PostMapping("/resolveTask")
    public ApiResult<Void> resolveTask(@RequestBody @Validated ResolveTaskRequest requestParam) {
        return processTaskService.resolveTask(requestParam);
    }

    /**
     * 查询用户已办任务
     *
     * @param businessKey 业务Key
     * @return 流程实例id
     */
    @GetMapping("/listDoneTask")
    public ApiResult<List<TaskVo>> listDoneTask(@RequestParam("businessKey") String businessKey) {
        SysUser userInfo = UserUtil.getUserInfo();
        return processTaskService.listDoneTask(userInfo, businessKey);
    }

    /**
     * 驳回流程实例
     *
     * @param requestParam 请求参数
     * @return 是否驳回成功
     */
    @PostMapping("/rejectProcessInstance")
    public ApiResult<String> rejectProcessInstance(@RequestBody @Validated RejectInstanceRequest requestParam) {
        return processInstanceService.rejectProcessInstance(requestParam);
    }

    /**
     * 设置流程实例变量
     *
     * @param requestParam 请求参数
     * @return 提示信息
     */
    @PostMapping("/setVariableByInstance")
    public ApiResult<String> setVariableByInstance(@RequestBody @Validated SetVariableRequest requestParam) {
        return processInstanceService.setVariableByInstance(requestParam);
    }

    /**
     * 挂起流程实例--可以设置/删除变量，其他操作将不被允许
     *
     * @param processInstanceId 流程实例id
     * @return 提示信息
     */
    @PostMapping("/suspendById")
    public ApiResult<String> suspendProcessInstanceById(@RequestParam("processInstanceId") String processInstanceId) {
        return processInstanceService.suspendProcessInstanceById(processInstanceId);
    }

    /**
     * 激活流程实例
     *
     * @param processInstanceId 流程实例id
     * @return 提示信息
     */
    @PostMapping("/activateById")
    public ApiResult<String> activateProcessInstanceById(@RequestParam("processInstanceId") String processInstanceId) {
        return processInstanceService.activateProcessInstanceById(processInstanceId);
    }

    /**
     * 删除流程实例
     *
     * @param processInstanceId 流程实例id
     * @return 提示信息
     */
    @DeleteMapping("/deleteProcessInstance")
    public ApiResult<String> deleteProcessInstance(@RequestParam("processInstanceId") String processInstanceId) {
        return processInstanceService.deleteProcessInstance(processInstanceId);
    }

    /**
     * 修改流程实例【这个接口可以实现很多功能，比如B节点驳回到A节点，换个思路就是希望流程实例从A节点重新开始】
     *
     * @param requestParam 请求参数
     * @return 提示信息
     */
    @PostMapping("/modifyProcessInstance")
    public ApiResult<String> modifyProcessInstance(@RequestBody @Validated ModifyInstanceRequest requestParam) {
        return processInstanceService.modifyProcessInstance(requestParam);
    }

    /**
     * 根据获取审批人方式不同，提供了V2版本，适用于审批人是通过执行监听器获取的方式。
     *
     * @param requestParam 请求参数
     * @return 提示信息
     */
    @PostMapping("/modifyProcessInstanceV2")
    public ApiResult<String> modifyProcessInstanceV2(@RequestBody @Validated ModifyInstanceRequest requestParam) {
        return processInstanceService.modifyProcessInstanceV2(requestParam);
    }

    /**
     * 查询流程实例节点状态，只包含历史和当前节点
     *
     * @param processInstanceId 流程实例id
     * @return k:节点id v:状态值
     */
    @GetMapping("/queryInstanceNodeState")
    public ApiResult<Map<String, Integer>> queryInstanceNodeState(@RequestParam("processInstanceId") String processInstanceId) {
        return processInstanceService.queryInstanceNodeState(processInstanceId);
    }
}
